/** @file vtparser_table.c
 *
 * @author Joshua Haberman <joshua@reverberate.org>
 * @author _modified by_ cameris <camerisdump@gmail.com>
 */

#include "vtparser_table.h"

/* state function prototypes */
uint8_t state_anywhere(uint8_t ch);
uint8_t state_csi_entry(uint8_t ch);
uint8_t state_csi_ignore(uint8_t ch);
uint8_t state_csi_intermediate(uint8_t ch);
uint8_t state_csi_param(uint8_t ch);
uint8_t state_dcs_entry(uint8_t ch);
uint8_t state_dcs_ignore(uint8_t ch);
uint8_t state_dcs_intermediate(uint8_t ch);
uint8_t state_dcs_param(uint8_t ch);
uint8_t state_dcs_passthrough(uint8_t ch);
uint8_t state_escape(uint8_t ch);
uint8_t state_escape_intermediate(uint8_t ch);
uint8_t state_ground(uint8_t ch);
uint8_t state_osc_string(uint8_t ch);
uint8_t state_sos_pm_apc_string(uint8_t ch);

/** @brief state function table */
uint8_t (*STATE_TABLE[15])(uint8_t ch) = {
	state_anywhere,
	state_csi_entry,
	state_csi_ignore,
	state_csi_intermediate,
	state_csi_param,
	state_dcs_entry,
	state_dcs_ignore,
	state_dcs_intermediate,
	state_dcs_param,
	state_dcs_passthrough,
	state_escape,
	state_escape_intermediate,
	state_ground,
	state_osc_string,
	state_sos_pm_apc_string,
};

/** @brief entry action table */
enum vtparse_action ENTRY_ACTIONS[] = {
   0,							/* none for ANYWHERE */
   VTPARSE_ACTION_CLEAR, 		/* CSI_ENTRY */
   0,							/* none for CSI_IGNORE */
   0,							/* none for CSI_INTERMEDIATE */
   0,							/* none for CSI_PARAM */
   VTPARSE_ACTION_CLEAR,		/* DCS_ENTRY */
   0,							/* none for DCS_IGNORE */
   0,							/* none for DCS_INTERMEDIATE */
   0,							/* none for DCS_PARAM */
   VTPARSE_ACTION_HOOK,			/* DCS_PASSTHROUGH */
   VTPARSE_ACTION_CLEAR,		/* ESCAPE */
   0,							/* none for ESCAPE_INTERMEDIATE */
   0,							/* none for GROUND */
   VTPARSE_ACTION_OSC_START,	/* OSC_STRING */
   0,							/* none for SOS_PM_APC_STRING */
};

/**< @brief exit action table */
enum vtparse_action EXIT_ACTIONS[] = {
   0,							/* none for ANYWHERE */
   0,							/* none for CSI_ENTRY */
   0,							/* none for CSI_IGNORE */
   0,							/* none for CSI_INTERMEDIATE */
   0,							/* none for CSI_PARAM */
   0,							/* none for DCS_ENTRY */
   0,							/* none for DCS_IGNORE */
   0,							/* none for DCS_INTERMEDIATE */
   0,							/* none for DCS_PARAM */
   VTPARSE_ACTION_UNHOOK,		/* DCS_PASSTHROUGH */
   0,							/* none for ESCAPE */
   0,							/* none for ESCAPE_INTERMEDIATE */
   0,							/* none for GROUND */
   VTPARSE_ACTION_OSC_END,		/* OSC_STRING */
   0,							/* none for SOS_PM_APC_STRING */
};

/** @brief state change in state VTPARSE_STATE_ANYWHERE
 * @param ch character
 * @return combined new state and action */
uint8_t state_anywhere(uint8_t ch)
{ /* {{{ */
	uint8_t result = 0;
	if ( ch == 24 || ch == 26 || (ch >= 128 && ch <= 143) ||
			(ch >= 145 && ch <=151) || ch == 153 || ch == 154 || ch == 156 ) {
		result = (VTPARSE_STATE_GROUND << 4) | VTPARSE_ACTION_EXECUTE;
	}
	else if ( ch == 27 ) {
		result = (VTPARSE_STATE_ESCAPE << 4);
	}
	else if ( ch == 144 ) {
		result = (VTPARSE_STATE_DCS_ENTRY << 4);
	}
	else if ( ch == 152 || ch == 158 || ch == 159 ) {
		result = (VTPARSE_STATE_SOS_PM_APC_STRING << 4);
	}
	else if ( ch == 155 ) {
		result = (VTPARSE_STATE_CSI_ENTRY << 4);
	}
	else if ( ch == 157 ) {
		result = (VTPARSE_STATE_OSC_STRING << 4);
	}
	return result;
} /* }}} */

/** @brief state change in state VTPARSE_STATE_CSI_ENTRY
 * @param ch character
 * @return combined new state and action */
uint8_t state_csi_entry(uint8_t ch)
{ /* {{{ */
	uint8_t result = 0;
	if ( (ch >= 0 && ch <= 23) || ch == 25 || (ch >= 28 && ch <= 31) ) {
		result = VTPARSE_ACTION_EXECUTE;
	}
	else if ( ch >= 32 && ch <= 47 ) {
		result = (VTPARSE_STATE_CSI_INTERMEDIATE << 4) | VTPARSE_ACTION_COLLECT;
	}
	else if ( (ch >= 48 && ch <= 57) || ch == 59 ) {
		result = (VTPARSE_STATE_CSI_PARAM << 4) | VTPARSE_ACTION_PARAM;
	}
	else if ( ch == 58 ) {
		result = (VTPARSE_STATE_CSI_IGNORE << 4);
	}
	else if ( ch >= 60 && ch <= 63 ) {
		result = (VTPARSE_STATE_CSI_PARAM << 4) | VTPARSE_ACTION_COLLECT;
	}
	else if ( ch >= 64 && ch <= 126 ) {
		result = (VTPARSE_STATE_GROUND << 4) | VTPARSE_ACTION_CSI_DISPATCH;
	}
	else if ( ch == 127 ) {
		result = VTPARSE_ACTION_IGNORE;
	}
	return result;
} /* }}} */

/** @brief state change in state VTPARSE_STATE_CSI_IGNORE
 * @param ch character
 * @return combined new state and action */
uint8_t state_csi_ignore(uint8_t ch)
{ /* {{{ */
	uint8_t result = 0;
	if ( (ch >= 0 && ch <= 23) || ch == 25 || (ch >= 28 && ch <= 31) ) {
		result = VTPARSE_ACTION_EXECUTE;
	}
	else if ( (ch >= 32 && ch <= 63) || ch == 127 ) {
		result = VTPARSE_ACTION_IGNORE;
	}
	else if ( ch >= 64 && ch <= 126 ) {
		result = (VTPARSE_STATE_GROUND << 4);
	}
	return result;
} /* }}} */

/** @brief state change in state VTPARSE_STATE_CSI_INTERMEDIATE
 * @param ch character
 * @return combined new state and action */
uint8_t state_csi_intermediate(uint8_t ch)
{ /* {{{ */
	uint8_t result = 0;
	if ( (ch >= 0 && ch <= 23) || ch == 25 || (ch >= 28 && ch <= 31) ) {
		result = VTPARSE_ACTION_EXECUTE;
	}
	else if ( ch >= 32 && ch <= 47 ) {
		result = VTPARSE_ACTION_COLLECT;
	}
	else if ( ch >= 48 && ch <= 63 ) {
		result = (VTPARSE_STATE_CSI_IGNORE << 4);
	}
	else if ( ch >= 64 && ch <= 126 ) {
		result = (VTPARSE_STATE_GROUND << 4) | VTPARSE_ACTION_CSI_DISPATCH;
	}
	else if ( ch == 127 ) {
		result = VTPARSE_ACTION_IGNORE;
	}
	return result;
} /* }}} */

/** @brief state change in state VTPARSE_STATE_CSI_PARAM
 * @param ch character
 * @return combined new state and action */
uint8_t state_csi_param(uint8_t ch)
{ /* {{{ */
	uint8_t result = 0;
	if ( (ch >= 0 && ch <= 23) || ch == 25 || (ch >= 28 && ch <= 31) ) {
		result = VTPARSE_ACTION_EXECUTE;
	}
	else if ( ch >= 32 && ch <= 47 ) {
		result = (VTPARSE_STATE_CSI_INTERMEDIATE << 4) | VTPARSE_ACTION_COLLECT;
	}
	else if ( (ch >= 48 && ch <= 57) || ch == 59 ) {
		result = VTPARSE_ACTION_PARAM;
	}
	else if ( ch == 58 || (ch >= 60 && ch <= 63) ) {
		result = (VTPARSE_STATE_CSI_IGNORE << 4);
	}
	else if ( ch >= 64 && ch <= 126 ) {
		result = (VTPARSE_STATE_GROUND << 4) | VTPARSE_ACTION_CSI_DISPATCH;
	}
	else if ( ch == 127 ) {
		result = VTPARSE_ACTION_IGNORE;
	}
	return result;
} /* }}} */

/** @brief state change in state VTPARSE_STATE_DCS_ENTRY
 * @param ch character
 * @return combined new state and action */
uint8_t state_dcs_entry(uint8_t ch)
{ /* {{{ */
	uint8_t result = 0;
	if ( (ch >= 0 && ch <= 23) || ch == 25 || (ch >= 28 && ch <= 31) ) {
		result = VTPARSE_ACTION_IGNORE;
	}
	else if ( ch >= 32 && ch <= 47 ) {
		result = (VTPARSE_STATE_DCS_INTERMEDIATE << 4) | VTPARSE_ACTION_COLLECT;
	}
	else if ( (ch >= 48 && ch <= 57) || ch == 59 ) {
		result = (VTPARSE_STATE_DCS_PARAM << 4) | VTPARSE_ACTION_PARAM;
	}
	else if ( ch == 58 ) {
		result = (VTPARSE_STATE_DCS_IGNORE << 4);
	}
	else if ( ch >= 60 && ch <= 63 ) {
		result = (VTPARSE_STATE_DCS_PARAM << 4) | VTPARSE_ACTION_COLLECT;
	}
	else if ( ch >= 64 && ch <= 126 ) {
		result = (VTPARSE_STATE_DCS_PASSTHROUGH << 4);
	}
	else if ( ch == 127 ) {
		result = VTPARSE_ACTION_IGNORE;
	}
	return result;
} /* }}} */

/** @brief state change in state VTPARSE_STATE_DCS_IGNORE
 * @param ch character
 * @return combined new state and action */
uint8_t state_dcs_ignore(uint8_t ch)
{ /* {{{ */
	uint8_t result = 0;
	if ( (ch >= 0 && ch <= 23) || ch == 25 || (ch >= 28 && ch <= 127) ) {
		result = VTPARSE_ACTION_IGNORE;
	}
	else if ( ch == 156 ) {
		result = (VTPARSE_STATE_GROUND << 4);
	}
	return result;
} /* }}} */

/** @brief state change in state VTPARSE_STATE_DCS_INTERMEDIATE
 * @param ch character
 * @return combined new state and action */
uint8_t state_dcs_intermediate(uint8_t ch)
{ /* {{{ */
	uint8_t result = 0;
	if ( (ch >= 0 && ch <= 23) || ch == 25 || (ch >= 28 && ch <= 31) ) {
		result = VTPARSE_ACTION_IGNORE;
	}
	else if ( ch >= 32 && ch <= 47 ) {
		result = VTPARSE_ACTION_COLLECT;
	}
	else if ( ch >= 48 && ch <= 63 ) {
		result = (VTPARSE_STATE_DCS_IGNORE << 4);
	}
	else if ( ch >= 64 && ch <= 126 ) {
		result = (VTPARSE_STATE_DCS_PASSTHROUGH << 4);
	}
	else if ( ch == 127 ) {
		result = VTPARSE_ACTION_IGNORE;
	}
	return result;
} /* }}} */

/** @brief state change in state VTPARSE_STATE_DCS_PARAM
 * @param ch character
 * @return combined new state and action */
uint8_t state_dcs_param(uint8_t ch)
{ /* {{{ */
	uint8_t result = 0;
	if ( (ch >= 0 && ch <= 23) || ch == 25 || (ch >= 28 && ch <= 31) ) {
		result = VTPARSE_ACTION_IGNORE;
	}
	else if ( ch >= 32 && ch <= 47 ) {
		result = (VTPARSE_STATE_DCS_INTERMEDIATE << 4) | VTPARSE_ACTION_COLLECT;
	}
	else if ( (ch >= 48 && ch <= 57) || ch == 59 ) {
		result = VTPARSE_ACTION_PARAM;
	}
	else if ( ch == 58 || (ch >= 60 && ch <= 63) ) {
		result = (VTPARSE_STATE_DCS_IGNORE << 4);
	}
	else if ( ch >= 64 && ch <= 126 ) {
		result = (VTPARSE_STATE_DCS_PASSTHROUGH << 4);
	}
	else if ( ch == 127 ) {
		result = VTPARSE_ACTION_IGNORE;
	}
	return result;
} /* }}} */

/** @brief state change in state VTPARSE_STATE_DCS_PASSTHROUGH
 * @param ch character
 * @return combined new state and action */
uint8_t state_dcs_passthrough(uint8_t ch)
{ /* {{{ */
	uint8_t result = 0;
	if ( (ch >= 0 && ch <= 23) || ch == 25 || (ch >= 28 && ch <= 126) ) {
		result = VTPARSE_ACTION_PUT;
	}
	else if ( ch == 127 ) {
		result = VTPARSE_ACTION_IGNORE;
	}
	else if ( ch == 156 ) {
		result = (VTPARSE_STATE_GROUND << 4);
	}
	return result;
} /* }}} */

/** @brief state change in state VTPARSE_STATE_ESCAPE
 * @param ch character
 * @return combined new state and action */
uint8_t state_escape(uint8_t ch)
{ /* {{{ */
	uint8_t result = 0;
	if ( (ch >= 0 && ch <= 23) || ch == 25 || (ch >= 28 && ch <= 31) ) {
		result = VTPARSE_ACTION_EXECUTE;
	}
	else if ( ch >= 32 && ch <= 47 ) {
		result = (VTPARSE_STATE_ESCAPE_INTERMEDIATE << 4) | VTPARSE_ACTION_COLLECT;
	}
	else if ( (ch >= 48 && ch <= 79) || (ch >= 81 && ch <= 87) || ch == 89 ||
			ch == 90 || ch == 92 || (ch >= 96 && ch <= 126) ) {
		result = (VTPARSE_STATE_GROUND << 4) | VTPARSE_ACTION_ESC_DISPATCH;
	}
	else if ( ch == 80 ) {
		result = (VTPARSE_STATE_DCS_ENTRY << 4);
	}
	else if ( ch == 88 || ch == 94 || ch == 95) {
		result = (VTPARSE_STATE_SOS_PM_APC_STRING << 4);
	}
	else if ( ch == 91 ) {
		result = (VTPARSE_STATE_CSI_ENTRY << 4);
	}
	else if ( ch == 93 ) {
		result = (VTPARSE_STATE_OSC_STRING << 4);
	}
	else if ( ch == 127 ) {
		result = VTPARSE_ACTION_IGNORE;
	}
	return result;
} /* }}} */

/** @brief state change in state VTPARSE_STATE_ESCAPE_INTERMEDIATE
 * @param ch character
 * @return combined new state and action */
uint8_t state_escape_intermediate(uint8_t ch)
{ /* {{{ */
	uint8_t result = 0;
	if ( (ch >= 0 && ch <= 23) || ch == 25 || (ch >= 28 && ch <= 31) ) {
		result = VTPARSE_ACTION_EXECUTE;
	}
	else if ( ch >= 32 && ch <= 47 ) {
		result = VTPARSE_ACTION_COLLECT;
	}
	else if ( ch >= 48 && ch <= 126 ) {
		result = (VTPARSE_STATE_GROUND << 4) | VTPARSE_ACTION_ESC_DISPATCH;
	}
	else if ( ch == 127 ) {
		result = VTPARSE_ACTION_IGNORE;
	}
	return result;
} /* }}} */

/** @brief state change in state VTPARSE_STATE_GROUND
 * @param ch character
 * @return combined new state and action */
uint8_t state_ground(uint8_t ch)
{ /* {{{ */
	uint8_t result = 0;
	if ( (ch >= 0 && ch <= 23) || ch == 25 || (ch >= 28 && ch <= 31) ||
			(ch >= 128 && ch <= 143) || (ch >= 145 && ch <= 154) || ch == 156 ) {
		result = VTPARSE_ACTION_EXECUTE;
	}
	else if ( (ch >= 32 && ch <= 127) || (ch >= 160 && ch <= 255) ) {
		result = VTPARSE_ACTION_PRINT;
	}
	return result;
} /* }}} */

/** @brief state change in state VTPARSE_STATE_OSC_STRING
 * @param ch character
 * @return combined new state and action */
uint8_t state_osc_string(uint8_t ch)
{ /* {{{ */
	uint8_t result = 0;
	if ( (ch >= 0 && ch <= 23) || ch == 25 || (ch >= 28 && ch <= 31) ) {
		result = VTPARSE_ACTION_IGNORE;
	}
	else if ( ch >= 32 && ch <= 127 ) {
		result = VTPARSE_ACTION_OSC_PUT;
	}
	else if ( ch == 156 ) {
		result = (VTPARSE_STATE_GROUND << 4);
	}
	return result;
} /* }}} */

/** @brief state change in state VTPARSE_STATE_SOS_PM_APC_STRING
 * @param ch character
 * @return combined new state and action */
uint8_t state_sos_pm_apc_string(uint8_t ch)
{ /* {{{ */
	uint8_t result = 0;
	if ( (ch >= 0 && ch <= 23) || ch == 25 || (ch >= 28 && ch <= 127) ) {
		result = VTPARSE_ACTION_IGNORE;
	}
	else if ( ch == 156 ) {
		result = (VTPARSE_STATE_GROUND << 4);
	}
	return result;
} /* }}} */

/* vim:set foldmethod=marker: */
